﻿using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq.Dynamic.Core;

namespace iWare.Wms.Application
{
    /// <summary>
    /// 出库管理
    /// </summary>
    [ApiDescriptionSettings("仓库作业", Name = "IExWarehouse", Order = 100)]
    [Route("api/[Controller]")]
    public class ExWarehouseService : IExWarehouseService, IDynamicApiController, ITransient
    {
        private readonly IRepository<WmsContainer, MasterDbContextLocator> _wmsContainerRep;
        private readonly IRepository<WmsMaterial, MasterDbContextLocator> _wmsMaterialRep;
        private readonly IRepository<WmsMaterialContainer, MasterDbContextLocator> _wmsMaterialContainerRep;
        private readonly IRepository<WmsArea, MasterDbContextLocator> _wmsAreaRep;
        private readonly IRepository<WmsPlace, MasterDbContextLocator> _wmsPlaceRep;
        private readonly IRepository<WmsTask, MasterDbContextLocator> _wmsTaskRep;
        private readonly IRepository<WmsMaterialStock, MasterDbContextLocator> _wmsMaterialStockRep;
        private readonly IRepository<WmsContainerPlace, MasterDbContextLocator> _wmsContainerPlaceRep;


        public ExWarehouseService(
            IRepository<WmsContainer, MasterDbContextLocator> wmsContainerRep,
            IRepository<WmsMaterial, MasterDbContextLocator> wmsMaterialRep,
            IRepository<WmsMaterialContainer, MasterDbContextLocator> wmsMaterialContainerRep,
            IRepository<WmsArea, MasterDbContextLocator> wmsAreaRep,
            IRepository<WmsPlace, MasterDbContextLocator> wmsPlaceRep,
            IRepository<WmsTask, MasterDbContextLocator> wmsTaskRep,
            IRepository<WmsMaterialStock, MasterDbContextLocator> wmsMaterialStockRep,
            IRepository<WmsContainerPlace, MasterDbContextLocator> wmsContainerPlaceRep
        )
        {
            _wmsContainerRep = wmsContainerRep;
            _wmsMaterialRep = wmsMaterialRep;
            _wmsMaterialContainerRep = wmsMaterialContainerRep;
            _wmsAreaRep = wmsAreaRep;
            _wmsPlaceRep = wmsPlaceRep;
            _wmsTaskRep = wmsTaskRep;
            _wmsMaterialStockRep = wmsMaterialStockRep;
            _wmsContainerPlaceRep = wmsContainerPlaceRep;
        }

        /// <summary>
        /// 分页查询库存表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("page")]
        public async Task<PageResult<WmsMaterialStockOutput>> Page([FromQuery] WmsMaterialStockSearch input)
        {
            var wmsMaterialStocks = await _wmsMaterialStockRep.DetachedEntities
                                     .Where(!string.IsNullOrEmpty(input.Materialno), u => EF.Functions.Like(u.MaterialNo, $"%{input.Materialno.Trim()}%"))
                                     .Where(input.Materialtype != null, u => u.MaterialType == input.Materialtype)
                                     .Where(!string.IsNullOrEmpty(input.Materialbatch), u => EF.Functions.Like(u.MaterialBatch, $"%{input.Materialbatch.Trim()}%"))
                                     .Where(!string.IsNullOrEmpty(input.Materialname), u => EF.Functions.Like(u.MaterialName, $"%{input.Materialname.Trim()}%"))
                                     .Where(!string.IsNullOrEmpty(input.Materialspec), u => EF.Functions.Like(u.MaterialSpec, $"%{input.Materialspec.Trim()}%"))
                                     .Where(input.Inspectionmethod != null, u => u.InspectionMethod == input.Inspectionmethod)
                                     .Where(input.Unittype != null, u => u.UnitType == input.Unittype)
                                     .Where(input.Unitno != null, u => u.UnitNo == input.Unitno)
                                     .Where(u => u.StockNumber != 0)
                                     .Where(!string.IsNullOrEmpty(input.Placecode), u => u.PlaceCode == input.Placecode)
                                     .Where(!string.IsNullOrEmpty(input.Containercode), u => u.ContainerCode == input.Containercode)
                                     .OrderBy(PageInputOrder.OrderBuilder(input))
                                     .ProjectToType<WmsMaterialStockOutput>()
                                     .ToADPagedListAsync(input.PageNo, input.PageSize);
            return wmsMaterialStocks;
        }

        /// <summary>
        /// 手动出库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("ManualWare")]
        [UnitOfWork]
        public async Task ManualWare(ExManualWarehouseInput input)
        {
            //检查是正在出库
            var isExit = await _wmsTaskRep.AnyAsync(n => n.TaskStatus != Core.Enum.TaskStatus.WANCHENG && n.ContainerCode==input.Containercode);
            if (isExit) throw Oops.Oh("存在出库任务!");
            //检查库位信息
            var placeModel = await _wmsPlaceRep.DetachedEntities.Where(p => p.PlaceCode == input.Placecode).ProjectToType<WmsPlace>().FirstOrDefaultAsync();
            if (placeModel == null) throw Oops.Oh("库位不存在!");
            if (placeModel.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");
            if (placeModel.PlaceStatus != Core.Enum.PlaceStatus.CUNHUO) throw Oops.Oh("库位异常货!");

            //容器信息
            var containerModel = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == input.Containercode && n.ContainerStatus == Core.Enum.ContainerStatus.KUWEI);
            if (containerModel == null) throw Oops.Oh("托盘信息不存在!");

            //库位容器关系
            var containerPlaceModel = await _wmsContainerPlaceRep.FirstOrDefaultAsync(p => p.ContainerCode == containerModel.ContainerCode
               && p.ContainerId == containerModel.Id && p.PlaceCode == placeModel.PlaceCode && p.PlaceId == placeModel.Id
               && p.ContainerPlaceStatus == CommonStatus.ENABLE);
            if (containerPlaceModel == null) throw Oops.Oh("库位容器关系不存在!");

            //库存物料信息
            var materialStockModelList = await _wmsMaterialStockRep.Where(n => n.ContainerCode == input.Containercode
            && n.PlaceCode == input.Placecode).ToListAsync();
            if (materialStockModelList.Count == 0) throw Oops.Oh("物料信息不存在!");

            //关系对应出库的物料
            var materialContainersList = await _wmsMaterialContainerRep.Where(p => p.ContainerCode == containerModel.ContainerCode
                && p.BindStatus == CommonStatus.ENABLE).ToListAsync();

            //单据号
            var orderNo = "N/A";
            //创建任务
            if (materialContainersList.Count > 0) orderNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString();
            var takmodel = new WmsTask()
            {
                TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
                TaskModel = Core.Enum.TaskModel.SHOUDONG,
                TaskType = Core.Enum.TaskType.CHUKU,
                TaskLevel = 1,
                TaskStatus = Core.Enum.TaskStatus.WANCHENG,
                ContainerCode = input.Containercode,
                SourcePlace = input.Placecode,
                Aisle = placeModel.Aisle,
                ToPlace = "N/A",
                AreaName = placeModel.WmsArea.AreaName,
                OrderNo = orderNo,
            };
            await _wmsTaskRep.InsertAsync(takmodel);
            //托盘状态
            if (orderNo == "N/A") containerModel.ContainerStatus = Core.Enum.ContainerStatus.KOUXIAN;
            else containerModel.ContainerStatus = Core.Enum.ContainerStatus.ZUPANG;
            await _wmsContainerRep.UpdateAsync(containerModel);
            //组盘信息
            //入库时组盘信息逻辑删除
            foreach (var item in materialContainersList)
            {
                //修改
                item.BindStatus = CommonStatus.DELETED;
                await _wmsMaterialContainerRep.UpdateAsync(item);
            }

            foreach (var item in materialContainersList)
            {
                //新增出库绑定记录  禁用
                var bindentranceModel = new WmsMaterialContainer()
                {
                    ContainerId = item.ContainerId,
                    ContainerCode = item.ContainerCode,
                    MaterialName = item.MaterialName,
                    MaterialNo = item.MaterialNo,
                    MaterialBatch = item.MaterialBatch,
                    MaterialSpec = item.MaterialSpec,
                    MaterialId = item.MaterialId,
                    BindQuantity = item.BindQuantity,
                    BindStatus = CommonStatus.DISABLE,
                    OrderNo = orderNo,
                };
                await _wmsMaterialContainerRep.InsertNowAsync(bindentranceModel);

                //新增组盘绑定记录 正常
                var newbindentranceModel = new WmsMaterialContainer()
                {
                    ContainerId = item.ContainerId,
                    ContainerCode = item.ContainerCode,
                    MaterialName = item.MaterialName,
                    MaterialNo = item.MaterialNo,
                    MaterialBatch = item.MaterialBatch,
                    MaterialSpec = item.MaterialSpec,
                    MaterialId = item.MaterialId,
                    BindQuantity = item.BindQuantity,
                    BindStatus = CommonStatus.ENABLE,
                    OrderNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
                };
                await _wmsMaterialContainerRep.InsertNowAsync(newbindentranceModel);
            }
            //库位
            placeModel.PlaceStatus = Core.Enum.PlaceStatus.KONGXIAN;
            placeModel.EmptyContainer = YesOrNot.N;
            await _wmsPlaceRep.UpdateAsync(placeModel);
            //修改库存
            foreach (var item in materialStockModelList)
            {
                item.PlaceCode = "N/A";
                item.AreaId = 0;
                item.StockNumber = 0;
                await _wmsMaterialStockRep.UpdateAsync(item);
            }
            //删除托盘库位关系
            containerPlaceModel.ContainerPlaceStatus = CommonStatus.DELETED;
            await _wmsContainerPlaceRep.UpdateAsync(containerPlaceModel);
        }


        /// <summary>
        /// 自动出库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("AutoWare")]
        [UnitOfWork]
        public async Task AutoWare(ExAutoWarehouseInput input)
        {
            //检查是正在出库
            var isExit = await _wmsTaskRep.AnyAsync(n => n.TaskStatus != Core.Enum.TaskStatus.WANCHENG && n.ContainerCode == input.Containercode);
            if (isExit) throw Oops.Oh("存在出库任务!");
            //检查库位信息
            var placeModel = await _wmsPlaceRep.DetachedEntities.Where(p => p.PlaceCode == input.Placecode).ProjectToType<WmsPlace>().FirstOrDefaultAsync();
            if (placeModel == null) throw Oops.Oh("库位不存在!");
            if (placeModel.Islock == YesOrNot.Y) throw Oops.Oh("库位被锁定!");
            if (placeModel.PlaceStatus != Core.Enum.PlaceStatus.CUNHUO) throw Oops.Oh("库位异常货!");

            //容器信息
            var containerModel = await _wmsContainerRep.FirstOrDefaultAsync(n => n.ContainerCode == input.Containercode && n.ContainerStatus == Core.Enum.ContainerStatus.KUWEI);
            if (containerModel == null) throw Oops.Oh("托盘信息不存在!");

            //库位容器关系
            var containerPlaceModel = await _wmsContainerPlaceRep.FirstOrDefaultAsync(p => p.ContainerCode == containerModel.ContainerCode
               && p.ContainerId == containerModel.Id && p.PlaceCode == placeModel.PlaceCode && p.PlaceId == placeModel.Id && p.ContainerPlaceStatus == CommonStatus.ENABLE);
            if (containerPlaceModel == null) throw Oops.Oh("库位容器关系不存在!");

            //物料信息
            var materialStockList = await _wmsMaterialStockRep.Where(n => n.ContainerCode == input.Containercode
            && n.PlaceCode == input.Placecode).ToListAsync();
            if (materialStockList.Count == 0) throw Oops.Oh("物料信息不存在!");

            //关系对应出库的物料
            var materialContainersList = await _wmsMaterialContainerRep.Where(n => n.ContainerCode == input.Containercode && n.BindStatus == CommonStatus.ENABLE).ToListAsync();


            //单据信息
            var orderNo = "N/A";
            if (materialContainersList.Count > 0) orderNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString();

            //创建任务
            var takmodel = new WmsTask()
            {
                TaskNo = Yitter.IdGenerator.YitIdHelper.NextId().ToString(),
                TaskModel = Core.Enum.TaskModel.ZIDONG,
                TaskType = Core.Enum.TaskType.CHUKU,
                TaskLevel = 1,
                Aisle=placeModel.Aisle,
                TaskStatus = Core.Enum.TaskStatus.WEIZHIXING,
                ContainerCode = input.Containercode,
                SourcePlace = input.Placecode,
                ToPlace = input.Entrance,
                AreaName = placeModel.WmsArea.AreaName,
                OrderNo = orderNo,
            };
            await _wmsTaskRep.InsertAsync(takmodel);
            //组盘信息
            foreach (var item in materialContainersList)
            {
                //修改
                item.BindStatus = CommonStatus.DISABLE;
                await _wmsMaterialContainerRep.UpdateAsync(item);
                //新增
                var bindentranceModel = new WmsMaterialContainer()
                {
                    ContainerId = item.ContainerId,
                    ContainerCode = item.ContainerCode,
                    MaterialName = item.MaterialName,
                    MaterialNo = item.MaterialNo,
                    MaterialBatch = item.MaterialBatch,
                    MaterialSpec = item.MaterialSpec,
                    MaterialId = item.MaterialId,
                    BindQuantity = item.BindQuantity,
                    BindStatus = CommonStatus.ENABLE,
                    OrderNo = orderNo,
                };
                await _wmsMaterialContainerRep.InsertNowAsync(bindentranceModel);
            }
            //库位
            placeModel.PlaceStatus = Core.Enum.PlaceStatus.DAICHU;
            await _wmsPlaceRep.UpdateAsync(placeModel);
           
        }

    }
}
